package com.smile.commons.gps;

import java.math.BigDecimal;
import java.util.Arrays;

public class CoordinateTransformUtil1 {
    // 地球半径
    private static final double EARTH_RADIUS = 6378245.0;
    private static final double EE = 0.00669342162296594323;
    private static final double PI = Math.PI;

    // 判断是否在中国境内
    private static boolean outOfChina(double lng, double lat) {
        return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
    }

    // 经纬度偏移量
    private static double transformLat(double lng, double lat) {
        double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    private static double transformLng(double lng, double lat) {
        double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }

    // WGS84 -> GCJ-02（大疆转高德）
    public static double[] wgs84ToGcj02(double lng, double lat) {
        if (outOfChina(lng, lat)) {
            return new double[]{lng, lat};
        }
        double dLat = transformLat(lng - 105.0, lat - 35.0);
        double dLng = transformLng(lng - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * PI;
        double magic = Math.sin(radLat);
        magic = 1 - EE * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * PI);
        dLng = (dLng * 180.0) / (EARTH_RADIUS / sqrtMagic * Math.cos(radLat) * PI);
        double mgLat = lat + dLat;
        double mgLng = lng + dLng;
        return new double[]{mgLng, mgLat};
    }

    // GCJ-02 -> WGS84（高德转大疆）
    public static double[] gcj02ToWgs84(double lng, double lat) {
        if (outOfChina(lng, lat)) {
            return new double[]{lng, lat};
        }
        double dLat = transformLat(lng - 105.0, lat - 35.0);
        double dLng = transformLng(lng - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * PI;
        double magic = Math.sin(radLat);
        magic = 1 - EE * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * PI);
        dLng = (dLng * 180.0) / (EARTH_RADIUS / sqrtMagic * Math.cos(radLat) * PI);
        double mgLat = lat + dLat;
        double mgLng = lng + dLng;
        return new double[]{lng * 2 - mgLng, lat * 2 - mgLat};
    }

    // GCJ-02 -> BD-09（高德转百度）
    public static double[] gcj02ToBd09(double lng, double lat) {
        double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * PI * 3000.0 / 180.0);
        double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * PI * 3000.0 / 180.0);
        double bdLng = z * Math.cos(theta) + 0.0065;
        double bdLat = z * Math.sin(theta) + 0.006;
        return new double[]{bdLng, bdLat};
    }

    // BD-09 -> GCJ-02（百度转高德）
    public static double[] bd09ToGcj02(double bdLng, double bdLat) {
        double x = bdLng - 0.0065;
        double y = bdLat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI * 3000.0 / 180.0);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI * 3000.0 / 180.0);
        double ggLng = z * Math.cos(theta);
        double ggLat = z * Math.sin(theta);
        return new double[]{ggLng, ggLat};
    }

    // WGS84 -> BD-09（大疆转百度）
    public static double[] wgs84ToBd09(double lng, double lat) {
        double[] gcj = wgs84ToGcj02(lng, lat);
        return gcj02ToBd09(gcj[0], gcj[1]);
    }

    // BD-09 -> WGS84（百度转大疆）
    public static double[] bd09ToWgs84(double bdLng, double bdLat) {
        double[] gcj = bd09ToGcj02(bdLng, bdLat);
        return gcj02ToWgs84(gcj[0], gcj[1]);
    }

    // 字符串高德坐标转大疆（如 "39.111,15.111" -> WGS84）
    public static double[] stringGcj02ToWgs84(String gcj02Str) {
        if (gcj02Str == null || !gcj02Str.contains(",")) {
            throw new IllegalArgumentException("输入格式应为 'lng,lat'");
        }
        String[] parts = gcj02Str.split(",");
        double lng = Double.parseDouble(parts[0].trim());
        double lat = Double.parseDouble(parts[1].trim());
        return gcj02ToWgs84(lng, lat);
    }

    // 大疆（WGS84）转高德（GCJ-02）字符串
    public static String wgs84ToGcj02String(double lng, double lat) {
        double[] gcj = wgs84ToGcj02(lng, lat);
        return gcj[0] + "," + gcj[1];
    }

    // WG384 其实就是 WGS84，如果不是请补充说明
    // 你可以直接用 wgs84ToGcj02、gcj02ToWgs84 等方法

    // 高德字符串坐标转大疆字符串坐标（GCJ-02字符串转WGS84字符串）
    public static String gcj02StringToWgs84String(String gcj02Str) {
        double[] wgs84 = stringGcj02ToWgs84(gcj02Str);
        return wgs84[0] + "," + wgs84[1];
    }

    // 大疆字符串坐标转高德字符串坐标（WGS84字符串转GCJ-02字符串）
    public static String wgs84StringToGcj02String(String wgs84Str) {
        if (wgs84Str == null || !wgs84Str.contains(",")) {
            throw new IllegalArgumentException("输入格式应为 'lng,lat'");
        }
        String[] parts = wgs84Str.split(",");
        double lng = Double.parseDouble(parts[0].trim());
        double lat = Double.parseDouble(parts[1].trim());
        double[] gcj = wgs84ToGcj02(lng, lat);
        return gcj[0] + "," + gcj[1];
    }

    // ================= BigDecimal 版本 =================
    // WGS84 -> GCJ-02（大疆转高德）
    public static BigDecimal[] wgs84ToGcj02(BigDecimal lng, BigDecimal lat) {
        double[] res = wgs84ToGcj02(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // GCJ-02 -> WGS84（高德转大疆）
    public static BigDecimal[] gcj02ToWgs84(BigDecimal lng, BigDecimal lat) {
        double[] res = gcj02ToWgs84(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // GCJ-02 -> BD-09（高德转百度）
    public static BigDecimal[] gcj02ToBd09(BigDecimal lng, BigDecimal lat) {
        double[] res = gcj02ToBd09(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // BD-09 -> GCJ-02（百度转高德）
    public static BigDecimal[] bd09ToGcj02(BigDecimal lng, BigDecimal lat) {
        double[] res = bd09ToGcj02(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // WGS84 -> BD-09（大疆转百度）
    public static BigDecimal[] wgs84ToBd09(BigDecimal lng, BigDecimal lat) {
        double[] res = wgs84ToBd09(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // BD-09 -> WGS84（百度转大疆）
    public static BigDecimal[] bd09ToWgs84(BigDecimal lng, BigDecimal lat) {
        double[] res = bd09ToWgs84(lng.doubleValue(), lat.doubleValue());
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // 字符串高德坐标转大疆（如 "39.111,15.111" -> WGS84）BigDecimal版本
    public static BigDecimal[] stringGcj02ToWgs84BigDecimal(String gcj02Str) {
        double[] res = stringGcj02ToWgs84(gcj02Str);
        return new BigDecimal[]{BigDecimal.valueOf(res[0]), BigDecimal.valueOf(res[1])};
    }

    // 高德字符串坐标转大疆字符串坐标（BigDecimal版本，保留原始字符串格式）
    public static String gcj02StringToWgs84StringBigDecimal(String gcj02Str) {
        BigDecimal[] wgs84 = stringGcj02ToWgs84BigDecimal(gcj02Str);
        return wgs84[0].toPlainString() + "," + wgs84[1].toPlainString();
    }

    // 大疆字符串坐标转高德字符串坐标（BigDecimal版本，保留原始字符串格式）
    public static String wgs84StringToGcj02StringBigDecimal(String wgs84Str) {
        if (wgs84Str == null || !wgs84Str.contains(",")) {
            throw new IllegalArgumentException("输入格式应为 'lng,lat'");
        }
        String[] parts = wgs84Str.split(",");
        BigDecimal lng = new BigDecimal(parts[0].trim());
        BigDecimal lat = new BigDecimal(parts[1].trim());
        BigDecimal[] gcj = wgs84ToGcj02(lng, lat);
        return gcj[0].toPlainString() + "," + gcj[1].toPlainString();
    }

    public static void main(String[] args) {
        BigDecimal[] bigDecimals = CoordinateTransformUtil.wgs84ToGcj02(new BigDecimal("1.11"), new BigDecimal("1.11"));
        System.out.println(Arrays.toString(bigDecimals));
    }

} 